package tw.cating.karmasaver.plurk;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import tw.cating.karmasaver.intef.finishListener;
import tw.cating.karmasaver.intef.finishListenerEx;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class plurkApi {
	private static final String API_KEY = "aje42Gt8TrPVUTMPy2PcnNkPQLB4zeim";
	private static final String BASIC_URL = "https://www.plurk.com/API/";
	private static final String API_LOGIN = "Users/login";
	private static final String API_ADDPLURK = "Timeline/plurkAdd";
	private static final String API_PLURKGET = "Timeline/getPlurks";
	private static final String API_RESPONSEGET = "Responses/get";
	private String username = "";
	private String password = "";
	private int mUid = 0;
	
	Context mContext = null;
	DefaultHttpClient mHttpClient = new DefaultHttpClient();
	finishListener mLoginListener = null;
	finishListener mPostListener = null;
	finishListenerEx mrssCheckListener = null;
	
	private boolean bLogined = false;
	
	public plurkApi(Context context) {
		mContext = context;
	}
	
	public void finish() {
		mHttpClient.getConnectionManager().shutdown();
		mHttpClient = null;
	}
	
	public Thread requestLogin(String uname, String passwd, finishListener l) {
		mLoginListener = l;
		username = uname;
		password = passwd;
        final Runnable runnable = new Runnable() {
            public void run() {
            	if (doLogin()) {
            		mHandler.sendEmptyMessage(LOGIN_SUCCESSED);
            	} else {
            		mHandler.sendEmptyMessage(LOGIN_FAILED);
            	}
            }
        };
        return performOnBackgroundThread(runnable);
	}
	
	public Thread requestPrivatePost(final String msg, finishListener l) {
		mPostListener = l;
        final Runnable runnable = new Runnable() {
            public void run() {
            	if (doPrivatePost(msg)) {
            		mHandler.sendEmptyMessage(POST_SUCCESSED);
            	} else {
            		mHandler.sendEmptyMessage(POST_FAILED);
            	}
            }
        };
        return performOnBackgroundThread(runnable);
	}
	
	public Thread requestPost(final String msg, finishListener l) {
		mPostListener = l;
        final Runnable runnable = new Runnable() {
            public void run() {
            	if (doPost(msg)) {
            		mHandler.sendEmptyMessage(POST_SUCCESSED);
            	} else {
            		mHandler.sendEmptyMessage(POST_FAILED);
            	}
            }
        };
        return performOnBackgroundThread(runnable);
	}
	
	public Thread checkRssNode(finishListenerEx l) {
		mrssCheckListener = l;
		final Runnable runnable = new Runnable() {
			public void run() {
				String url;
				try {
					url = BASIC_URL + API_PLURKGET + "?api_key=" + API_KEY + "&limit=1&filter=only_user";
					HttpGet get = new HttpGet(url);
					
					if (mHttpClient != null) {
						final HttpResponse resp = mHttpClient.execute(get);
						if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
							if (mrssCheckListener != null) {
								mrssCheckListener.onFinish(convertStreamToString(resp.getEntity().getContent()));
							}
						} else {
							if (mrssCheckListener != null) {
								mrssCheckListener.onFinish(null);
							}
						}
					} 
				} catch (UnsupportedEncodingException e1) {
					// TODO Auto-generated catch block
					if (mrssCheckListener != null) {
						mrssCheckListener.onFinish(null);
					}
					e1.printStackTrace();
				} catch (ClientProtocolException e) {
					// TODO Auto-generated catch block
					if (mrssCheckListener != null) {
						mrssCheckListener.onFinish(null);
					}
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					if (mrssCheckListener != null) {
						mrssCheckListener.onFinish(null);
					}
					e.printStackTrace();
				}
			}
		};
		return performOnBackgroundThread(runnable);
	}
	
	public Thread getResponse(final int plurk_id, final finishListenerEx l) {
		final Runnable runnable = new Runnable() {
			public void run() {
				String url;
				try {
					url = BASIC_URL + API_RESPONSEGET + "?api_key=" + API_KEY + "&plurk_id=" + plurk_id;
					HttpGet get = new HttpGet(url);
					
					if (mHttpClient != null) {
						final HttpResponse resp = mHttpClient.execute(get);
						if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
							if (l != null) {
								l.onFinish(convertStreamToString(resp.getEntity().getContent()));
							}
						} else {
							if (l != null) {
								l.onFinish(null);
							}
						}
					} 
				} catch (UnsupportedEncodingException e1) {
					// TODO Auto-generated catch block
					if (l != null) {
						l.onFinish(null);
					}
					e1.printStackTrace();
				} catch (ClientProtocolException e) {
					// TODO Auto-generated catch block
					if (l != null) {
						l.onFinish(null);
					}
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					if (l != null) {
						l.onFinish(null);
					}
					e.printStackTrace();
				}
			}
		};
		return performOnBackgroundThread(runnable);
	}
	
    /**
     * Executes the network requests on a separate thread.
     * 
     * @param runnable The runnable instance containing network mOperations to
     *        be executed.
     */
    public static Thread performOnBackgroundThread(final Runnable runnable) {
        final Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    runnable.run();
                } finally {

                }
            }
        };
        t.start();
        return t;
    }
    
    public String convertStreamToString(InputStream is) {   
        /*  
         * To convert the InputStream to String we use the BufferedReader.readLine()  
         * method. We iterate until the BufferedReader return null which means  
         * there's no more data to read. Each line will appended to a StringBuilder  
         * and returned as String.  
         */  
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));   
        StringBuilder sb = new StringBuilder();   
    
        String line = null;   
        try {   
            while ((line = reader.readLine()) != null) {   
                sb.append(line + "\n");   
            }   
        } catch (IOException e) {   
            e.printStackTrace();   
        } finally {   
            try {   
                is.close();   
            } catch (IOException e) {   
                e.printStackTrace();   
            }   
        }   
    
        return sb.toString();   
    }
    
    protected void praseUid(String JSONString) {
    	try {
			JSONObject obj = new JSONObject(JSONString);
			if (obj.has("user_info")) {
				JSONObject uinfo = obj.getJSONObject("user_info");
				mUid = uinfo.getInt("uid");
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
	
	protected boolean doLogin() {
		if (bLogined)
			return bLogined;
		
		String url = BASIC_URL + API_LOGIN + "?api_key=" + API_KEY + "&username=" + username + "&password=" + password;
		HttpGet get = new HttpGet(url);
		final HttpResponse resp;
		try {
			if (mHttpClient != null) {
				resp = mHttpClient.execute(get);
				if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
					praseUid(convertStreamToString(resp.getEntity().getContent()));
//					Log.i("Cating", convertStreamToString(resp.getEntity().getContent()));
					bLogined = true;
				}
			}
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return bLogined;
	}
	
	protected boolean doPrivatePost(String msg) {
		boolean bPosted = false;
		String url;
		try {
			url = BASIC_URL + API_ADDPLURK + "?api_key=" + API_KEY + "&limited_to=[" + mUid + "]&qualifier=says&content=" + URLEncoder.encode(msg, "UTF-8");
			Log.i("Cating", "doPost:" + url);
			HttpGet get = new HttpGet(url);
			
			if (mHttpClient != null) {
				final HttpResponse resp = mHttpClient.execute(get);
				if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
					bPosted = true;
				}
			} 
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return bPosted;
	}
	
	protected boolean doPost(String msg) {
		boolean bPosted = false;
		String url;
		try {
			url = BASIC_URL + API_ADDPLURK + "?api_key=" + API_KEY + "&qualifier=says&content=" + URLEncoder.encode(msg, "UTF-8");
			Log.i("Cating", "doPost:" + url);
			HttpGet get = new HttpGet(url);
			
			if (mHttpClient != null) {
				final HttpResponse resp = mHttpClient.execute(get);
				if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
					bPosted = true;
				}
			} 
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return bPosted;
	}
	
	public boolean isLogined() {
		return bLogined;
	}
	
	public static final int LOGINRESULT_SUCCESSED = 0;
	public static final int LOGINRESULT_FAILED = 1;
	public static final int POSTRESULT_SUCCESSED = 0;
	public static final int POSTRESULT_FAILED = 1;
	
	private final static int LOGIN_SUCCESSED = 1;
	private final static int LOGIN_FAILED = 2;
	private final static int POST_SUCCESSED = 3;
	private final static int POST_FAILED = 4;
	Handler mHandler = new Handler() {
		@Override
		public void dispatchMessage(Message msg) {
			// TODO Auto-generated method stub
			switch (msg.what) {
			case LOGIN_SUCCESSED:
				if (mLoginListener != null)
					mLoginListener.onFinish(LOGINRESULT_SUCCESSED);
				break;
			case LOGIN_FAILED:
				if (mLoginListener != null)
					mLoginListener.onFinish(LOGINRESULT_FAILED);
				break;
			case POST_SUCCESSED:
				if (mPostListener != null)
					mPostListener.onFinish(POSTRESULT_SUCCESSED);
				break;
			case POST_FAILED:
				if (mPostListener != null)
					mPostListener.onFinish(POSTRESULT_FAILED);
				break;
			default:
				break;
			}
		}	
	};
}
